package ch03.com.friendsofed.isometric
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.geom.Rectangle;

	/**
	 * 创建地面、世界、对象列表和排序算法，使用单一类来统一处理这些问题。
	 */
	public class IsoWorld extends Sprite
	{
		private var _floor:Sprite;
		private var _objects:Array;
		private var _world:Sprite;

		public function IsoWorld()
		{
			_floor = new Sprite();
			addChild(_floor);

			_world = new Sprite();
			addChild(_world);

			_objects = new Array();
		}

		public function addChildToWorld(child:IsoObject):void
		{
			_world.addChild(child);
			_objects.push(child);
			sort();
		}

		public function addChildToFloor(child:IsoObject):void
		{
			_floor.addChild(child);
		}

		public function sort():void
		{
			_objects.sortOn("depth", Array.NUMERIC);
			for each (var dis:DisplayObject in _objects)
			{
				_world.addChild(dis);
			}
		}

		/**
		 * 这个函数接收一个IsoObject 对象作为参数，返回该参数对象在下一个速度上的位置是否
		   可行。
		   如果回去看一眼IsoObject 类，会发现有一个rect 属性。它用来描述对象所占的xz
		   面的
		   区域。通过这个rect 属性的offset（偏移）函数，可以算出对象下一个速度的位置。
		   然后遍历对象列表，检测三个环节：
		   第一，检查一下遍历的对象是否为传入对象本身。你总不会关心自己是否碰到自己吧。
		   第二，检测遍历的对象是否标记为可通过（可通过的意思是说另一个对象可否占据相
		   同的位置）。因 为有时候一个对象很扁，可 以被当做是块地板直接通过，有 时候是一种升降板，
		   升上去后允许角色可以从下面穿过的。
		   第三，检测偏移后的 rect 是否和其它对象的 rect 有交错，这点可以用内置的
		   Rectangle.intersects 函数轻易办到。
		   当此三个检测环节对列表中的任何一个对象为 true 时，说明不能移动，那么立即返回
		   false。如果完整的通过遍历，就说明不会有碰撞，可以放心的移动，那么才返回 true。在以
		   当前速度移动前，要先使用canMove 检测一下是否可行。
		 * @param	obj
		 * @return
		 */
		public function canMove(obj:IsoObject):Boolean
		{
			var rect:Rectangle = obj.rect;
			rect.offset(obj.vx, obj.vz);
			for each (var objB:IsoObject in _objects) 
			{
				if (obj != objB && !objB.walkable && rect.intersects(objB.rect))
				{
					return false;
				}
			}
			return true;
		}
	}
}